
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.BizObj.basic;
using Swaf.Container;
using Swaf.Resource;
using Swaf.Security;

namespace Swaf.Gui.AspNet2
{
    public abstract class BaseBizObjUserControl : UserControl
    {
        private static IClassFactory s_bizObjFieldFactory = null;
        protected IApplication m_app = Swaf.Application.currentApp;
        public event BizObjSelectedInfo BizObjSelected;
		protected bool m_createActiveOnLoad = true;

        private IBizObj m_currentBizObj;
		protected IMap m_basicLocalMacroValues;
        protected DictionaryStack m_localMacroValues;

        protected Privileges m_editPriv = Privileges.ReadOnly;
        protected string m_editTemplate = null;
        protected string m_readOnlyTemplate = null;
        protected IDictionary m_styleClassNames = new Hashtable();

		public BaseBizObjUserControl()
		{
		}

		public BaseBizObjUserControl(ActiveWidget widget)
			:base(widget)
		{
		}

		public string Resolve(string sr)
		{
			return Application.currentApp.resMgr.resolve(sr, LocalMacros);
		}
		public string ImageResolve(string sr)
		{
			string imgName = Application.currentApp.resMgr.resolve(sr, LocalMacros);
			if (imgName.EndsWith("/"))
				imgName = getBlankImageRef();
			return imgName;
		}

		public string getBizObj(string fieldName)
		{
			object v = null;
			if(CurrentBizObj != null)
				v = CurrentBizObj.get(fieldName);
			return v == null ? "" : v.ToString();
		}

		protected string getBlankImageRef()
		{
			string imgName = m_app.resMgr.resolve("/$mediaCacheName$/blank.gif.image", LocalMacros);
			if (imgName.StartsWith("/$"))
				imgName = m_app.resMgr.resolve("/$product.mediaCacheName$/blank.gif.image", LocalMacros);
			return imgName;
		}

		protected virtual void swappingOutExistingControl(BaseBizObjUserControl other)
		{
		}
		protected override void OnLoad(EventArgs e)
		{
			if (true)//m_createActiveOnLoad)
			{
				ActiveWidget act = null;
				//if (BPC.ActiveWidgets.ContainsKey(WidgetId))
				//{
				//    return;
				//    act = BPC.ActiveWidgets[WidgetId];
				//    BaseBizObjUserControl other = act.Widget as BaseBizObjUserControl;
				//    act.Widget = this;

				//    //swappingOutExistingControl(other);
				//    //BPC.ActiveWidgets.Remove(WidgetId);
				//    //other.Parent.Controls.Remove(other);
				//}
                bool hasOfflineStateAlready = BPC.getWidgetOfflineState(WidgetId) != null;
				WidgetOfflineState offlineState = State;
				if (act == null)
				{
					act = new ActiveWidget(this, BPC, offlineState);
                    act.CreatedFromPage = !hasOfflineStateAlready;
					BPC.defineActiveWidget(act);
				}

				//act.CreatedFromPage = Page.GetType().Name.CompareTo("ajaxrequesthandler_aspx") != 0;
				if (offlineState.State.get("editPriv") is Privileges)
					m_editPriv = (Privileges)offlineState.State.get("editPriv");
				if (offlineState.State.get("m_editTemplate") == null)
					offlineState.State.put("m_editTemplate", m_editTemplate);
				if (offlineState.State.get("m_readOnlyTemplate") == null)
					offlineState.State.put("m_readOnlyTemplate", m_readOnlyTemplate);
				if (offlineState.State.get("m_templateBizRule") == null)
					offlineState.State.put("m_templateBizRule", m_templateBizRule);
				if (offlineState.State.get("m_templateNameBizRule") == null)
					offlineState.State.put("m_templateNameBizRule", m_templateNameBizRule);
				if (State.State.get("m_basicLocalMacroValues") == null)
				{
					if (m_basicLocalMacroValues == null)
						m_basicLocalMacroValues = new FlexiMap();
					if (m_localMacroValues == null)
						m_localMacroValues = new DictionaryStack(m_basicLocalMacroValues);
					State.State.put("m_basicLocalMacroValues", m_basicLocalMacroValues);
				}
				else
				{
					m_basicLocalMacroValues = (IMap)State.State.get("m_basicLocalMacroValues");
					m_localMacroValues = new DictionaryStack(m_basicLocalMacroValues);
				}
			}
			base.OnLoad(e);

		}

		protected override void OnUnload(EventArgs e)
		{
			base.OnUnload(e);
			DictionaryStack s = (DictionaryStack)LocalMacros;
			if (s.Stack.Count == 3)
				s.Stack.RemoveRange(1, 2);
		}
		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);
		}

		public string styleClass(string name)
        {
            string v = (string)m_styleClassNames[name];
            return v == null ? "" : v;
        }

        public void setClass(string className, string classValue)
        {
            m_styleClassNames[className] = classValue;
        }


        protected void addLocalMacro(string keyName, object value)
        {
			LocalMacros[keyName] = value;
        }

		protected void bizObjSelected(IBizObj obj, string info)
		{
			if (BizObjSelected != null)
				BizObjSelected(this, obj, info);
		}

		public object Macro(string name) 
		{ 
			string v = LocalMacros[name] as string;
			if (v == null)
				return name;
			return Swaf.Application.currentApp.resMgr.resolve(v, LocalMacros); 
		}
		
		public IDictionary LocalMacros 
		{ 
			get 
			{
				if(m_basicLocalMacroValues == null)
					m_basicLocalMacroValues = (IMap)getOffline("m_basicLocalMacroValues");
				if (m_basicLocalMacroValues == null)
					m_basicLocalMacroValues = new FlexiMap();
				if (m_localMacroValues == null)
					m_localMacroValues = new DictionaryStack(m_basicLocalMacroValues);
				return m_localMacroValues;
			} 
		}

        public override string ContentName
        {
            get
            {
				string template = null;
				if (EditPrivilege <= Privileges.ReadOnly)
					template = (string)getOffline("m_readOnlyTemplate") == null ? (string)getOffline("m_editTemplate") : (string)getOffline("m_readOnlyTemplate");
				else
					template = (string)getOffline("m_editTemplate") == null ? (string)getOffline("m_readOnlyTemplate") : (string)getOffline("m_editTemplate");
				if (template == null)
                    template = base.ContentName;
				if (template!=null && template.Contains("$"))
					return m_app.resMgr.resolve(template, LocalMacros);
				return m_contentName = template;
            }
        }

        /// <summary></summary>
		public Privileges EditPrivilege { get { return (Privileges)getOffline("m_editPriv"); } set { putOffline("m_editPriv", value); } }

        /// <summary></summary>
		public virtual string ReadOnlyTemplate { get { return (string)getOffline("m_readOnlyTemplate"); } set { putOffline("m_readOnlyTemplate", value); } }

        /// <summary></summary>
        public virtual string EditableTemplate { get { return (string)getOffline("m_editTemplate"); }	set { putOffline("m_editTemplate", value); }}

		public IBizObj CurrentBizObj
		{
			get { return m_currentBizObj; }
			protected set
			{
				m_currentBizObj = value;
				m_localMacroValues = (DictionaryStack)LocalMacros;
				m_localMacroValues["_controlId"] = WidgetId;
				if (State != null && State.ParentBizProcIds.Count != 0)
					LocalMacros["Parent"] = State.ParentBizProcIds[0];
				if (m_localMacroValues.Stack.Count >= 2)
				{
					m_localMacroValues.Stack[1] =new NameAddressSupportDictionaryWrapper(value);
					if(State.ParentBizProcIds.Count != 0)
						if(m_localMacroValues.Stack.Count > 2)
							m_localMacroValues.Stack[2] =new NameAddressSupportDictionaryWrapper(BPC.getActiveBizProc(State.ParentBizProcIds[0]));
						else
							m_localMacroValues.Stack.Add(new NameAddressSupportDictionaryWrapper(BPC.getActiveBizProc(State.ParentBizProcIds[0])));
				}
				else
				{
					m_localMacroValues.Stack.Add(new NameAddressSupportDictionaryWrapper(value));
					if (State != null && State.ParentBizProcIds.Count != 0)
						m_localMacroValues.Stack.Add(new NameAddressSupportDictionaryWrapper(BPC.getActiveBizProc(State.ParentBizProcIds[0])));
				}
				//LocalMacros = m_localMacroValues;
			}
		}

		public virtual string CurrentBizObjTypeName
		{
			get
			{
				if (CurrentBizObj != null)
					return CurrentBizObj.type.Name;
				return "";
			}
		}

        protected virtual void processField(string fieldName)
        {
            processField(fieldName, fieldName);
        }
        protected virtual void processField(string fieldName, string ctlName)
        {
            Control ctl = this.FindControl(ctlName);
            if (ctl == null)
                return;
            processControl(ctl, fieldName);
        }

        protected virtual bool processControl(Control ctl)
        {
            return processControl(ctl, ctl.ID);
        }

		protected virtual bool isContainer(Control ctl)
		{
			return ctl.Controls.Count > 0;
		}

        protected virtual string getProperBizObjFieldName(string fieldName)
        {
            //Because '.' cannot be embedded in a control id, deep name address support
            //is provided by using the '_' as the '.' in the control id.  This means auto 
            //field mapping cannot use fields with embedded '_' in them.
            string fname = fieldName.Replace("___", " ").Replace("__", "$");
            if (fname.Length != fieldName.Length)
                fieldName = Swaf.Application.currentApp.resMgr.resolve(fname, LocalMacros);
            fieldName = fieldName.Replace('_', '.');
            return fieldName;
        }

        protected virtual bool processControl(Control ctl, string fieldName)
        {
            Debug.Assert(m_currentBizObj != null);
            Debug.Assert(ctl != null);

            string fieldVal = null;
			bool processed = true;

            try
            {
				if (isContainer(ctl))
					foreach (Control childCtl in ctl.Controls)
						if(childCtl.ID != "" && childCtl.ID != null)
							processControl(childCtl, childCtl.ID);

                if (fieldName != null && fieldName != "")
                {
                    fieldName = getProperBizObjFieldName(fieldName);

                    object orgFld = null;
                    if (m_currentBizObj.containsField(fieldName))
                    {
                        orgFld = m_currentBizObj.get(fieldName);
                        fieldVal = orgFld==null?"":orgFld.ToString();
                    }
					if (processControl(m_currentBizObj, ctl, fieldName, ref fieldVal))
					{
						if (ctl is ITextControl)
						{
							ITextControl txt = (ITextControl)ctl;
							string orgTxt = txt.Text;
							if (orgTxt != "" && orgFld is DateTime)
							{
								DateTime dt = (DateTime)orgFld;
								txt.Text = dt.ToString(orgTxt);
							}
							else if (ctl is TextBox && ((TextBox)ctl).TextMode == TextBoxMode.Password)
								((TextBox)ctl).Attributes.Add("value", fieldVal);
							else
								txt.Text = resolve(ctl, "text", fieldVal);
							//if (txt is TextBox)
							//    ((TextBox)txt).ReadOnly = m_privilege < Privileges.ReadOnly;
						}
						else if (ctl is IButtonControl)
						{
							IButtonControl btn = (IButtonControl)ctl;
							btn.Click += new EventHandler(BizObjField_Click);
							if (ctl is ImageButton)
							{
								Application.currentApp.Log.println(Swaf.Logging.LoggingLevels.High, "IButton imageUrl starting fieldVal = '{0}'", fieldVal);
								Image img = (Image)ctl;
								if (Cmn.IsEmpty(fieldVal) || fieldVal.EndsWith("/"))
									img.ImageUrl = "";
								else
                                    img.ImageUrl = resolve(ctl, "imageurl", fieldVal).Replace("//", "/");
							}
							else
								btn.Text = resolve(ctl, "text", fieldVal);
							if (ctl is ActionButton)
							{
								((ActionButton)btn).TriggerParam = resolve(ctl, "triggerparam", null);
								((ActionButton)btn).Actions = resolve(ctl, "actions", ((ActionButton)btn).Actions);
							}
						}
						else if (ctl is Image)
						{
							Application.currentApp.Log.println(Swaf.Logging.LoggingLevels.High, "Image imageUrl starting fieldVal = '{0}'", fieldVal);
							Image img = (Image)ctl;
                            string val = resolve(ctl, "imageurl", fieldVal).Replace("//", "/");
							if (Cmn.IsEmpty(val) || val.EndsWith("/"))
								img.ImageUrl = getBlankImageRef();
							else
								img.ImageUrl = val;
						}
						else if (ctl is System.Web.UI.WebControls.CheckBox)
						{
							System.Web.UI.WebControls.CheckBox chk = (System.Web.UI.WebControls.CheckBox)ctl;
							if (ctl.UniqueID != Page.Request.Form["__EVENTTARGET"])
							{
								if (fieldVal == "True" && !chk.Checked)
									chk.Checked = true;
								else if (fieldVal == "False" && chk.Checked)
									chk.Checked = false;
							}
							if (chk.AutoPostBack == true)
								chk.CheckedChanged += new EventHandler(BizObjField_Click);
						}
						else if (ctl is CheckBox)
						{
							CheckBox chk = (CheckBox)ctl;
							if (ctl.UniqueID != Page.Request.Form["__EVENTTARGET"])
							{
								if (fieldVal == "True" && !chk.Checked)
									chk.Checked = true;
								else if (fieldVal == "False" && chk.Checked)
									chk.Checked = false;
							}
						}
						else if (ctl is HyperLink)
						{
							BasePage bpage = Page as BasePage;
							HyperLink hyp = (HyperLink)ctl;
							string url = resolve(ctl, "navigateurl", fieldVal);
							if (bpage != null)
								url = bpage.processUrl(url);
							hyp.NavigateUrl = url;
                            hyp.ImageUrl = resolve(ctl, "imageurl", hyp.ImageUrl).Replace("//", "/");
							if (hyp.ImageUrl.EndsWith("/"))
								hyp.ImageUrl = "";
							hyp.Text = resolve(ctl, "text", fieldVal);
						}
						else if (ctl is DropDownList)
						{
							DropDownList ddl = (DropDownList)ctl;
							ListItem li = ddl.Items.FindByValue(fieldVal);
							for (int p = 0; p < ddl.Items.Count; p++)
								if (ddl.Items[p].Value.Equals(fieldVal))
								{
									ddl.SelectedIndex = p;
									break;
								}
							//if (li != null)
							//    li.Selected = true;
						}
						else if (ctl is IBizObjListDisplay)
						{
							((IBizObjListDisplay)ctl).SelectedBizObjKeyValue = orgFld;
						}
                        //else if (ctl.GetType().FullName == "FreeTextBoxControls.FreeTextBox" || ctl.GetType().FullName == "Syrinx.Gui.AspNet.Ajax.CkEditor")
                        //{
                        //    Cmn.callPropertySet(ctl, "Text", resolve(ctl, "text", fieldVal));
                        //}
						else if (ctl.GetType().FullName == "FredCK.FCKeditorV2.FCKeditor")
						{
							Cmn.callPropertySet(ctl, "Value", resolve(ctl, "value", fieldVal));
						}
						else if (ctl.GetType().FullName == "Syrinx.Gui.AspNet.DropDownCalendar")
						{
							Cmn.callPropertySet(ctl, "Text", resolve(ctl, "text", fieldVal));
						}

						else if (ctl is HiddenField)
							((HiddenField)ctl).Value = fieldVal;
						else
							processed = false;
					}
					else
					{
						if (ctl is HyperLink)
						{
							HyperLink hyp = (HyperLink)ctl;
							BasePage bpage = Page as BasePage;
							string url = resolve(ctl, "navigateurl", hyp.NavigateUrl);
							if (bpage != null)
								url = bpage.processUrl(url);
							hyp.NavigateUrl = url;
                            hyp.ImageUrl = resolve(ctl, "imageurl", hyp.ImageUrl).Replace("//", "/");
						}
						else if (ctl is HtmlButton)
						{
							HtmlButton b = (HtmlButton)ctl;
							string c = b.Attributes["onclick"] = m_app.resMgr.resolve(b.Attributes["onclick"], LocalMacros);
						}
						else if (ctl is HtmlControl)
						{
							HtmlControl c = (HtmlControl)ctl;
							c.Style[HtmlTextWriterStyle.BackgroundImage] = m_app.resMgr.resolve(c.Style[HtmlTextWriterStyle.BackgroundImage], LocalMacros);
						}
						else if (ctl is IButtonControl)
						{
							IButtonControl btn = (IButtonControl)ctl;
							btn.Click += new EventHandler(BizObjField_Click);
							if (ctl is ImageButton)
							{
								Image img = (Image)ctl;
								if (fieldVal == null || fieldVal.Length == 0)
									img.Visible = false;
								else
                                    img.ImageUrl = resolve(ctl, "imageurl", null).Replace("//", "/");
							}
							else
								btn.Text = resolve(ctl, "text", null);
						}
						else if (ctl is DivLayers)
						{
							if (Cmn.IsEmpty(ctl.SkinID))
							{
								string v = resolve(ctl, "cssclass", null);
								if (v != null)
									Cmn.callPropertySet(ctl, "CssClass", v);
								v = resolve(ctl, "numlayers", null);
								if (v != null)
									Cmn.callPropertySet(ctl, "NumLayers", v);
							}
						}
						else if (ctl is BizProc)
						{
							BizProc b = (BizProc)ctl;
							b.setupState(m_app.resMgr.resolve(b.OrigionalInnerState, LocalMacros));
						}
						else if (ctl is ComplexBizObjListDisplay)
						{
							ComplexBizObjListDisplay comp = (ComplexBizObjListDisplay)ctl;
							DictionaryStack dics = comp.LocalMacros as DictionaryStack;
							IDictionary dic = null;
							if (comp.State.State.containsField("_cmacs"))
								dic = comp.State.State["_cmacs"] as IDictionary;
							else
							{
								dic = dics.Stack[0];
								comp.State.State["_cmacs"] = dic;
							}

							FlexiMap m = new FlexiMap();
							//IDictionary m = dics.Stack[0];
							foreach (DictionaryEntry di in dic)
								m[di.Key] = m_app.resMgr.resolve(di.Value.ToString(), LocalMacros).Replace("$#", "$");
							dics.Stack[0] = m;
						}
						else if (ctl.GetType().FullName == "Articles.Gui.AspNet.StandAloneArticleListDisplay")
						{
							Cmn.callPropertySet(ctl, "PID", resolve(ctl, "pid", null));
						}

						processed = false;
					}
                }
                else
                    processed = false;
            }
            catch
            {
                //TODO: Now what?
				processed = false;
            }
			return processed;
        }

		protected internal override void processChildSkinId(Control child)
		{
			if (child is DivLayers)
			{
				Cmn.callPropertySet(child, "SkinID", resolve(child, "skinid", null));
				child.ApplyStyleSheetSkin(Page);
			}
		}

        /// <summary>
        /// This will use the single name provide for both finding the control and
        /// as the field name from the bizobj.  
        /// </summary>
        /// <param name="controlAndBizObjFieldName"></param>
        protected void updateBizObjField(string controlAndBizObjFieldName)
        {
            updateBizObjField(FindControl(controlAndBizObjFieldName));
        }

        protected void updateBizObjField(string ctlName, string bizObjFieldName)
        {
            updateBizObjField(FindControl(ctlName), bizObjFieldName);
        }

        protected void updateBizObjField(Control ctl)
        {
            string fieldName = ctl.ID;
            //Because '.' cannot be embedded in a control id, deep name address support
            //is provided by using the '_' as the '.' in the control id.  This means auto 
            //field mapping cannot use fields with embedded '_' in them.
			if (fieldName == null)
				fieldName = "";
			if(fieldName.Length>0 && fieldName[0] != '_')
				fieldName = fieldName.Replace('_', '.');
            updateBizObjField(ctl, fieldName);
        }

        /// <summary>
        /// This is the root implementation for all the updateBizObjField methods in this class.
        /// It does the work of getting the user's input from the control and pushing it into the
        /// bizobj field on the CurrentBizObj property of this object.
        /// </summary>
        /// <remarks>This method will only work with known control types.  It currently works
        /// with:
        /// ITextControl, FreeTextBox, and Checkbox.
        /// </remarks>
        /// <param name="ctl">The control to get the users input from</param>
        /// <param name="fieldName">The name of the bizobj field to put the value into.
        /// This can be a deep name address support field.</param>
        protected void updateBizObjField(Control ctl, string fieldName)
        {
            if (ctl == null)
                return;
            try
            {
				if (isContainer(ctl))
					foreach (Control childCtl in ctl.Controls)
						if (childCtl.ID != "" && childCtl.ID != null)
							updateBizObjField(childCtl);

				IBizObj bizObj = getBizObjFromControl(ctl, ref fieldName);
				if (bizObj == null)
					return;
				//BizObjField fldDef = bizObj.type.getField(fieldName, false) as BizObjField;
				bool isSingle=NameAddress.isSingleAddress(fieldName);
				BizObjField fldDef = isSingle?bizObj.type.getField(fieldName, false) as BizObjField:null;
				if (fldDef == null && !isSingle)
				{
					object o = bizObj.get(NameAddress.getAllButLast(fieldName));
					if(o is IBizObj)
						fldDef = ((IBizObj)o).type.getField(NameAddress.getLastAddress(fieldName), false) as BizObjField;
				}
				if (fldDef == null)
                    return;

                object ctlValue = null;
				if (processBizObjFieldFromControl(bizObj, fldDef, ctl) && (ctlValue = getControlValueForBizObjField(ctl, fldDef, bizObj, fieldName, false)) != null && !ctlValue.Equals(bizObj.get(fieldName)))
					updateBizObj(bizObj, fieldName, ctlValue);
            }
            catch
            {
                //TODO: Now what?
            }

        }

		protected virtual void updateBizObj(IBizObj bizObj, string fieldName, object newVal)
		{
            object orgVal = bizObj.get(fieldName);
			if((orgVal == null && newVal != null) || (orgVal != null && !orgVal.Equals(newVal)))
				bizObj.put(fieldName, newVal);
		}

		protected virtual object getControlValueForBizObjField(Control ctl, BizObjField fldDef, IBizObj obj, string fullFieldName, bool convertType)
		{
			object ctlValue = null;
			if (ctl is ITextControl)
			{
				if (ctl is TextBox && ((TextBox)ctl).TextMode == TextBoxMode.Password)
					ctlValue = ((TextBox)ctl).Attributes["value"];
				if(Cmn.IsEmpty(ctlValue))
					ctlValue = ((ITextControl)ctl).Text;
			}
			else if (ctl is CheckBox)
				ctlValue = ((CheckBox)ctl).Checked;
			else if (ctl is System.Web.UI.WebControls.CheckBox)
				ctlValue = ((System.Web.UI.WebControls.CheckBox)ctl).Checked;
			else if (ctl.GetType().FullName == "FreeTextBoxControls.FreeTextBox" || ctl.GetType().FullName == "Syrinx.Gui.AspNet.Ajax.CkEditor")
				ctlValue = Cmn.callPropertyGet(ctl, "Text");
			else if (ctl.GetType().FullName == "FredCK.FCKeditorV2.FCKeditor")
				ctlValue = Cmn.callPropertyGet(ctl, "Value");
			else if (ctl is DropDownList)
				ctlValue = ((DropDownList)ctl).SelectedValue;
			else if (ctl is System.Web.UI.WebControls.DropDownList)
				ctlValue = ((System.Web.UI.WebControls.DropDownList)ctl).SelectedValue;
			else if (ctl is HiddenField)
				ctlValue = ((HiddenField)ctl).Value;
			else if (ctl is Image)
				ctlValue = ((Image)ctl).ImageUrl;
			else if (ctl is HtmlInputFile)
			{
                //Because of the special nature of file upload, this is handled a bit
                //differenty than the other fields by having direct knowledge of the FileSysFile
                //bizobj type and using its fields
				HtmlInputFile f = (HtmlInputFile)ctl;
                IBizObj fObj = obj.type.Name.CompareTo("FileSysFile")==0?obj:m_app.bizObjMgr.create("FileSysFile");
				FileInfo fileInfo = new FileInfo(f.PostedFile.FileName);
				fObj.put("name", fileInfo.Name);
                ctlValue = new Swaf.Binary(f.PostedFile.InputStream, true);
                if (fObj != obj)
                {
                    fObj.put("data", ctlValue);
                    ctlValue = fObj;
                }
			}
			else if (ctl.GetType().FullName == "Syrinx.Gui.AspNet.DropDownCalendar")
				ctlValue = Cmn.callPropertyGet(ctl, "Text");
			else if (ctl is HyperLink)
				ctlValue = ((HyperLink)ctl).NavigateUrl;

			if (convertType && ctlValue != null && fldDef != null)
				ctlValue = createPlatformTypeInstance(fldDef, ctlValue);

			return ctlValue;
		}

        protected virtual string resolve(Control ctl, string fldName, object defaultValue)
        {
			string val = null;
			IDictionary d = OrigionalControls[ctl.ID] as IDictionary;
			if (d == null)
			{
				object curVal = Cmn.callPropertyGet(ctl, fldName, false);
				if (!Cmn.IsEmpty(curVal))
				{
					val = lastResolve(curVal.ToString());
					//val = m_app.resMgr.resolve(curVal.ToString(), LocalMacros);
					//if (val.CompareTo(curVal) != 0)
						return val;
				}
			}

			val = (string)(d == null ? defaultValue : d[fldName]);
			if (val != null && val.Length > 0)
				val = lastResolve(val);

			if (d != null && (val != d[fldName] as string || defaultValue == null/* || "".Equals(defaultValue)*/))
				defaultValue = val;

            return defaultValue==null?null:defaultValue.ToString();
        }

		protected virtual string lastResolve(string val)
		{
			val = m_app.resMgr.resolve(val, LocalMacros);
			return (!val.Contains("$#"))?val:m_app.resMgr.resolve(val.Replace("$#","$"), LocalMacros);
		}

        protected void BizObjField_Click(object sender, EventArgs e)
        {
            string baseCtlId = null;
            Control ctl = sender as Control;
            IBizObj selectedBizObj = getBizObjFromControl(ctl, ref baseCtlId);

            if (selectedBizObj != null)
            {
                ViewState["sid"] = selectedBizObj.KeyValue;
                if (BizObjSelected != null)
                    BizObjSelected(this, selectedBizObj, baseCtlId);
            }
        }

        protected abstract IBizObj getBizObjFromControl(Control ctl, ref string baseCtlId);

        protected virtual bool processControl(IBizObj obj, Control ctl, string fldName, ref string fldValue)
        {
			return obj.containsField(fldName) || ctl is IButtonControl;
        }

        protected virtual bool processBizObjFieldFromControl(IBizObj obj, IBizObjField fld, Control ctl)
        {
			return !(ctl is Image) && !(ctl is ReadOnlyText);
        }

        #region IWidget Members


        #endregion

        /// <summary>
        /// This method will attempt to convert the given value (val) into the type expected
        /// by the field.  This method does NOT perform magic.  If the field type doesn't support
        /// being created by the type passed this method will fail.  IF the field is a bizobj or
        /// bizobjlist type, it will use val as a string and trying processing it as XML.  If this
        /// method cannot convert the type, it will log an entry in the application log.
        /// </summary>
        /// <param name="field">The bizobj field definition to use for the destination type.</param>
        /// <param name="val">The source value to convert from.</param>
        /// <returns>The converted type if possible or the origional type if the conversion could not
        /// be done.</returns>
        protected object createPlatformTypeInstance(BizObjField field, object val)
        {
            try
            {
                if (val != null && val.GetType() == field.PlatformType)
                    return val;
				if (field.BizType == BizFieldType.NetClass)
				{
					if (val != null)
					{
						if (val is string && ((string)val).Length == 0)
							val = BizObjFieldFactory.createFromNickName(field.FactoryType);
						else
							val = BizObjFieldFactory.createFromNickName(field.FactoryType, val);
					}
				}
				else if (field.BizType == BizFieldType.BizObj)
				{
					IBizObjDefinition def = Application.globalApp.bizObjMgr.getDefinition(field.FactoryType);
					if (def != null)
					{
						XmlTextReader xml = new XmlTextReader(new StringReader(val.ToString()));
						xml.MoveToContent();
						val = FullBizObj.createInstance(def.Name, def, xml);
					}
				}
				else if (field.BizType == BizFieldType.BizObjList)
				{
					XmlTextReader xml = new XmlTextReader(new StringReader(val.ToString()));
					xml.MoveToContent();
					val = FullBizObjList.createInstance(null, null, xml);
				}
            }
            catch
            {
                //If val cannot be converted to the platform type of the field, the best thing to do
                //is to let val be returned unconverted.  
                Application.globalApp.Log.write(String.Format("Unable to convert a '{0}' to a '{1}' for bizobj field '{2}.{3}'",
                    (val == null) ? "null" : val.GetType().Name, field.PlatformType.Name, field.Parent.Name, field.Name));
            }

            return val;
        }

        /// <summary>
        /// The factory for bizobj fields.  This is a shortcut for getting access to the factory and
        /// the actual instance is pulled from the application factories on first use.
        /// </summary>
        public static IClassFactory BizObjFieldFactory
        {
            get
            {
                if (s_bizObjFieldFactory == null)
                    s_bizObjFieldFactory = Application.currentApp.factories["BizObjBizFieldTypes"];
                return s_bizObjFieldFactory;
            }
        }

		protected override void AddParsedSubObject(object obj)
		{
			System.Web.UI.LiteralControl control = (System.Web.UI.LiteralControl)obj;
			if (control.Text.Trim().Length != 0)
			{
				XmlDocument doc = new XmlDocument();
				doc.LoadXml(control.Text);
				m_basicLocalMacroValues = new FlexiMap(doc.DocumentElement);
				m_localMacroValues = new DictionaryStack(new NameAddressSupportDictionaryWrapper(m_basicLocalMacroValues));
				//if (m_localMacroValues == null)
				//	m_localMacroValues = new DictionaryStack(m_basicLocalMacroValues);
				//m_localMacroValues = new DictionaryStack(new Nanew FlexiMap(doc.DocumentElement);
				//We need to use m_localMacroValues here rather than LocalMacros because LocalMacros property
				//tries to use the BPC state, which has not been setup when this method is called by the ASPX
				//processing.  The only time this method is called is during ASPX processing.
				//m_localMacroValues.Stack.Add(new NameAddressSupportDictionaryWrapper(new FlexiMap(doc.DocumentElement)));
			}
		}
	}
}
